﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using SipII.Parameter;

namespace SipII
{
    /// <summary>
    /// 会话信息
    /// </summary>
    public class Session
    {
        /// <summary>
        /// 终端的位置代码
        /// </summary>
        public string LocationCode { set; get; }

        /// <summary>
        /// 终端的位置说明
        /// </summary>
        public string TerminalLocation { set; get; }

        /// <summary>
        /// 终端的登录账号
        /// </summary>
        public string LoginUserId { set; get; }

        /// <summary>
        /// 终端的登录密码
        /// </summary>
        public string LoginPassword { set; get; }

        /// <summary>
        /// 终端的状态代码
        /// </summary>
        public char StatusCode { set; get; }

        /// <summary>
        /// 终端支持的SIP协议版本
        /// </summary>
        public string ProtocolVersion { set; get; }

        /// <summary>
        /// 最后发给终端的消息
        /// </summary>
        public string LastResponse { set; get; }

        /// <summary>
        /// 终端上的当前读者的ID
        /// </summary>
        public string PatronIdentifier { set; get; }

        /// <summary>
        /// 终端上的当前读者的密码
        /// </summary>
        public string PatronPassword { set; get; }

        /// <summary>
        /// 终端每行最大打印宽度
        /// </summary>
        public string MaxPrintWidth { set; get; }
    }

    public class Sip2ServerProxy
    {
        /// <summary>
        /// 存放SC终端信息
        /// Key = login user id
        /// Value = login password = terminal password
        /// 当终端状态改变，需同步
        /// </summary>
        public static Dictionary<string, Session> Sessiones = new Dictionary<string, Session>() { };

        /// <summary>
        /// 对ACS设备发送的命令进行回复
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public static string Response(string terminalId, string requestCmd)
        {
            if (!requestCmd.EndsWith("\n"))
                requestCmd += "\n";

            //是否启用错误检测
            bool errorDetectionEnable = Properties.Settings.Default.ErrorDetectionEnable && Regex.IsMatch(requestCmd, "AZ[0-9a-fA-F]{4}\\n");

            bool requestCmdIsvalid = true;

            if (errorDetectionEnable)
            {
                //检查requestCmd的有效性
                string message = requestCmd.Substring(0, requestCmd.Length - 5);
                string checksum = requestCmd.Substring(requestCmd.Length - 5, 4);

                requestCmdIsvalid = checksum == computeCheckSum(message);
            }

            string responseMsg;

            if (!requestCmdIsvalid)
            {
                responseMsg = new SipII.Message.RequestScResend().ToString();
            }
            else
            {
                ISip2Server objSip2Server;

                switch (Properties.Settings.Default.ILSName.ToLower())
                {
                    case "nm2000":
                        objSip2Server = new Sip2Server4Nm2000();
                        break;
                    case "milnets":
                        objSip2Server = new Sip2Server4Milnets();
                        break;
                    default:
                        objSip2Server = new Sip2Server4Nm2000();
                        break;
                }

                //命令代码
                int cmdId;

                if (int.TryParse(requestCmd.Substring(0, 2), out cmdId))
                {
                    //分别响应不同的命令请求
                    switch ((enumCmdId)cmdId)
                    {
                        case enumCmdId.PatronStatus:
                            responseMsg = objSip2Server.PatronStatusResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.Checkout:
                            responseMsg = objSip2Server.CheckoutResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.Checkin:
                            responseMsg = objSip2Server.CheckinResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.BlockPatron:
                            responseMsg = objSip2Server.BlockPatronResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.ScStatus:
                            responseMsg = objSip2Server.AcsStatus(terminalId, requestCmd);
                            break;
                        case enumCmdId.Login:
                            responseMsg = objSip2Server.LoginResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.PatronInformation:
                            responseMsg = objSip2Server.PatronInformationResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.EndPatronSession:
                            responseMsg = objSip2Server.EndSessionResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.FeePaid:
                            responseMsg = objSip2Server.FeePaidResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.ItemInformation:
                            responseMsg = objSip2Server.ItemInformationResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.PatronEnable:
                            responseMsg = objSip2Server.PatronEnableResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.Hold:
                            responseMsg = objSip2Server.HoldResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.Renew:
                            responseMsg = objSip2Server.RenewResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.RenewAll:
                            responseMsg = objSip2Server.RenewAllResponse(terminalId, requestCmd);
                            break;
                        case enumCmdId.RequestAcsResend:
                            lock (Sessiones)
                            {
                                responseMsg = Sessiones[terminalId].LastResponse;
                            }

                            return responseMsg;
                        default:
                            responseMsg = new SipII.Message.RequestScResend().ToString();
                            break;
                    }
                }
                else
                {
                    responseMsg = new SipII.Message.RequestScResend().ToString();
                }
            }

            if (errorDetectionEnable)
            {
                // 增加校验字符串
                responseMsg += Sip2Parameter.dicFieldId[enumFieldName.checksum.ToString()];

                responseMsg += computeCheckSum(responseMsg);
            }

            responseMsg += "\n";

            //保存最后一次的回复消息
            lock (Sessiones)
            {
                if (Sessiones.ContainsKey(terminalId))
                {
                    Sessiones[terminalId].LastResponse = responseMsg;
                }
                else
                {
                    Session session = new Session();

                    session.LastResponse = responseMsg;

                    Sessiones.Add(terminalId, session);
                }
            }

            return responseMsg;
        }

        /// <summary>
        /// 计算消息的校验数据
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        private static string computeCheckSum(string message)
        {
            char[] chrMessage = message.ToCharArray();

            UInt32 checksum = 0;

            for (int i = 0; i < chrMessage.Length; i++)
            {
                checksum += (UInt32)chrMessage[i];
            }

            checksum = (UInt32)(-(checksum & 0xFFFF));

            string result = checksum.ToString("X");

            result = result.Substring(result.Length - 4, 4);

            return result;
        }
    }
}
